package net.xdclass.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import net.xdclass.constant.CacheKey;
import net.xdclass.enums.BizCodeEnum;
import net.xdclass.exception.BizException;
import net.xdclass.interceptor.LoginInterceptor;
import net.xdclass.mapper.ProductMapper;
import net.xdclass.model.LoginUser;
import net.xdclass.model.ProductDO;
import net.xdclass.request.CartItemRequest;
import net.xdclass.service.CartService;
import net.xdclass.vo.CartItemVo;
import net.xdclass.vo.CartVo;
import org.assertj.core.util.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Classname CartServiceImpl
 * @Description TODO
 * @Date 2022/5/11 15:45
 * @Created by sunhao
 */
@Service
public class CartServiceImpl implements CartService {

  @Autowired
  private StringRedisTemplate redisTemplate;

  @Autowired
  private ProductMapper productMapper;

  @Override
  public void addToCart(CartItemRequest cartItemRequest) {
    BoundHashOperations<String, Object, Object> myCartOps = getMyCartOps();
    Object cacheObj = myCartOps.get(cartItemRequest.getProductId());
    if (cacheObj != null) {
      //存在更新数量
      CartItemVo cartItemVo = JSON.parseObject(cacheObj.toString(), CartItemVo.class);
      cartItemVo.setBuyNum(cartItemRequest.getBuyNum() + cartItemVo.getBuyNum());
      myCartOps.put(cartItemRequest.getProductId(), JSON.toJSONString(cartItemVo));
    } else {
      ProductDO productDO = productMapper.selectOne(new QueryWrapper<ProductDO>().eq("id", cartItemRequest.getProductId()));
      if (productDO == null) {
        throw new BizException(BizCodeEnum.PRODUCT_NOT_EXIT);
      }
      //不存在 添加
      CartItemVo cartItemVo = new CartItemVo();
      cartItemVo.setAmount(productDO.getAmount());
      cartItemVo.setBuyNum(cartItemRequest.getBuyNum());
      cartItemVo.setTitle(productDO.getTitle());
      cartItemVo.setCoverImg(productDO.getCoverImg());
      cartItemVo.setProductId(productDO.getId());
      myCartOps.put(cartItemRequest.getProductId(), JSON.toJSONString(cartItemVo));
    }
  }

  @Override
  public CartVo list(Boolean latestPrice) {
    BoundHashOperations<String, Object, Object> myCartOps = getMyCartOps();
    CartVo cartVo = new CartVo();
    List<Long> productIdList = Lists.newArrayList();
    List<CartItemVo> cartItemVoList = Objects.requireNonNull(myCartOps.values()).stream().map(x -> {
      CartItemVo cartItemVo = JSON.parseObject(x.toString(), CartItemVo.class);
      productIdList.add(cartItemVo.getProductId());
      return cartItemVo;
    }).collect(Collectors.toList());


    if (latestPrice) {
      setProductLatestPrise(cartItemVoList, productIdList);
    }
    cartVo.setCartItemVoList(cartItemVoList);
    return cartVo;
  }

  private void setProductLatestPrise(List<CartItemVo> cartItemVoList, List<Long> productIdList) {
    if(CollectionUtils.isEmpty(cartItemVoList) || CollectionUtils.isEmpty(productIdList)){
      return;
    }
    List<ProductDO> productDOList = productMapper.selectList(new QueryWrapper<ProductDO>().in("id", productIdList));
    Map<Long, ProductDO> productDOMap = productDOList.stream().collect(Collectors.toMap(ProductDO::getId, Function.identity()));
    cartItemVoList.forEach(cartItemVo -> {
      ProductDO productDO = productDOMap.get(cartItemVo.getProductId());
      cartItemVo.setAmount(productDO.getAmount());
      cartItemVo.setTitle(productDO.getTitle());
      cartItemVo.setCoverImg(productDO.getCoverImg());
    });
  }

  @Override
  public void clear() {
    redisTemplate.delete(getCartKey());
  }

  @Override
  public void delete(String productId) {
    BoundHashOperations<String, Object, Object> myCartOps = getMyCartOps();
    myCartOps.delete(productId);
  }

  @Override
  public void update(CartItemRequest cartItemRequest) {
    BoundHashOperations<String, Object, Object> myCartOps = getMyCartOps();
    Object result = myCartOps.get(cartItemRequest.getProductId());
    if (result == null) {
      throw new BizException(BizCodeEnum.ORDER_CONFIRM_CART_ITEM_NOT_EXIST);
    }
    CartItemVo cartItemVo = JSON.parseObject(result.toString(), CartItemVo.class);
    cartItemVo.setBuyNum(cartItemRequest.getBuyNum() + cartItemVo.getBuyNum());
    myCartOps.put(cartItemRequest.getProductId(), JSON.toJSONString(cartItemVo));
  }

  @Override
  public List<CartItemVo> confirmOrderCartItem(List<Long> productIdList) {
    //获取全部购物车的购物项
    CartVo list = list(true);
    List<CartItemVo> cartItemVoList = list.getCartItemVoList();
    //根据需要的商品id进行过滤，并清空对应的购物项
    return cartItemVoList.stream().filter(obj -> {
      if (productIdList.contains(obj.getProductId())) {
        this.delete(obj.getProductId().toString());
        return true;
      }
      return false;
    }).collect(Collectors.toList());
  }

  private BoundHashOperations<String, Object, Object> getMyCartOps() {
    return redisTemplate.boundHashOps(getCartKey());
  }


  private String getCartKey() {
    LoginUser loginUser = LoginInterceptor.threadLocal.get();
    return String.format(CacheKey.CART_KEY, loginUser.getId());
  }

}
